﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using GameEngine;
using System.Windows.Controls.Primitives;
using System.Windows.Threading;
using Tomers.WPF.Localization;

namespace Daphne.Controls
{
    /// <summary>
    /// Interaction logic for FigureCountControl.xaml
    /// </summary>
    public partial class GameStateControl : UserControl
    {
        private MoveItem _boardItem;
        private bool _bWhiteTurnFirst = true;
        private GameManager _mng;

        private List<StrengthMenuItem> _lstStrengthContextMenu = new List<StrengthMenuItem>()
        {
            new StrengthMenuItem() { TextKey = "CTR_MoveStrength1" , MoveStrength = string.Empty },
            new StrengthMenuItem() { TextKey = "CTR_MoveStrength2" , MoveStrength = "!!"},
            new StrengthMenuItem() { TextKey = "CTR_MoveStrength3", MoveStrength = "!"},
            new StrengthMenuItem() { TextKey = "CTR_MoveStrength4", MoveStrength = "?"},
            new StrengthMenuItem() { TextKey = "CTR_MoveStrength5", MoveStrength = "??"},
            new StrengthMenuItem() { TextKey = "CTR_MoveStrength6", MoveStrength = "!?"},
            new StrengthMenuItem() { TextKey = "CTR_MoveStrength7", MoveStrength = "?!" }
        };

        public event EventHandler<NotationChangedArgs> NotationChangedEvent;

        public GameStateControl()
        {
            InitializeComponent();
            uxNumberNotation.Click += new RoutedEventHandler(uxNumberNotation_Click);
            uxGameList.HorizontalContentAlignment = System.Windows.HorizontalAlignment.Stretch;
            uxGameList.SelectionChanged += (obj, e) =>
              Dispatcher.BeginInvoke(DispatcherPriority.Render, new Action(() =>
                uxGameList.UnselectAll()));
            uxGameList.MouseDoubleClick += uxGameList_MouseDoubleClick;
            uxGameList.MouseRightButtonUp += uxGameList_MouseRightButtonUp;
        }

        private void LocalizeContextMenu()
        {
            foreach (var item in _lstStrengthContextMenu)
            {
                item.DisplayText = GetMoveStrength(item.TextKey);
            }
        }

        private bool FindCellCoordinates(DependencyObject dep, out int rowidx, out int colidx)
        {
            rowidx = -1;
            colidx = -1;

            //Stepping through the visual tree
            while ((dep != null) && !(dep is System.Windows.Controls.DataGridCell))
            {
                dep = VisualTreeHelper.GetParent(dep);
            }

            //Is the dep a cell or outside the bounds of Window1?
            if (dep == null | !(dep is System.Windows.Controls.DataGridCell))
            {
                return false;
            }
            else
            {
                System.Windows.Controls.DataGridCell cell = new System.Windows.Controls.DataGridCell();
                cell = (System.Windows.Controls.DataGridCell)dep;
                while ((dep != null) && !(dep is DataGridRow))
                {
                    dep = VisualTreeHelper.GetParent(dep);
                }

                if (dep == null)
                {
                    return false;
                }
                int colindex = cell.Column.DisplayIndex - 1;  //this returns COLUMN INDEX

                DataGridRow row = dep as DataGridRow;
                System.Windows.Controls.DataGrid dataGrid = ItemsControl.ItemsControlFromItemContainer(row) as System.Windows.Controls.DataGrid;
                int rowindex = dataGrid.ItemContainerGenerator.IndexFromContainer(row);

                rowidx = rowindex;
                colidx = colindex;

                return true;
            }
        }

        void uxGameList_MouseRightButtonUp(object sender, MouseButtonEventArgs e)
        {
            DependencyObject dep = (DependencyObject)e.OriginalSource;
            int rowindex, colindex;

            // if not found cell coordinates, exit
            if (FindCellCoordinates(dep, out rowindex, out colindex) == false)
                return;

            if (colindex < 0)
                return;

            // find move
            MoveItem moveItem = uxGameList.Items[rowindex] as MoveItem;
            Move move = colindex == 0 ? moveItem.WhiteMoveObject : moveItem.BlackMoveObject;
            if (move == null)
                return;

            LocalizeContextMenu();

            ContextMenu menu = new ContextMenu();
            foreach (var item in _lstStrengthContextMenu)
            {
                MenuItem menuItem = new MenuItem();
                menuItem.Header = item.DisplayText;
                menuItem.Click += new RoutedEventHandler( (snd, eargs) =>
                    {
                        move.MoveStrength = item.MoveStrength;
                        RefreshGameList();
                    });
                menu.Items.Add(menuItem);
            }

            Point p = e.GetPosition(null);

            menu.PlacementTarget = uxGameList;
            menu.IsOpen = true;    
        }


        void uxGameList_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            DependencyObject dep = (DependencyObject)e.OriginalSource;
            int rowindex, colindex;

            // if not found cell coordinates, exit
            if (FindCellCoordinates(dep, out rowindex, out colindex) == false)
                return;

            if (colindex < 0)
                return;

            int moveIndex = rowindex * 2 + colindex;
            if (_bWhiteTurnFirst == false)
                moveIndex -= 1;

            if (MoveSetEvent != null)
            {
                MoveSetEventArgs eArgs = new MoveSetEventArgs();
                eArgs.MoveIndex = moveIndex;
                MoveSetEvent(this, eArgs);
            }



        }

        #region ITabControl Members

        public GameManager GameManager
        {
            get
            {
                return _mng;
            }
            set
            {
                _mng = value;
                uxPDNEditor.GameManager = value;
            }
        }

        public event EventHandler<MoveSetEventArgs> MoveSetEvent;

        public void Update()
        {
            if (GameManager != null)
            {
                RefreshGameList();
                uxPDNEditor.Update();
            }
        }


        protected void RefreshGameList()
        {
            uxGameList.Items.Clear();

            if (this.GameManager == null)
                return;
            List<Move> dummyList = new List<Move>();
            this.GameManager.MoveHistory.GetMoveList(dummyList);
            if (dummyList.Count == 0)
                return;

            int moveIndex = 1;
            _boardItem = null;

            // verify, what move is first
            bool firstMove = true;
            int mi = this.GameManager.MoveHistory.GetMoveIndex();
            this.GameManager.MoveHistory.MoveToBeginning();
            if (this.GameManager.GameBoard.OnMove == enumFigureColor.Black)
                firstMove = false;

            _bWhiteTurnFirst = firstMove == true;

            this.GameManager.MoveHistory.MoveToIndex(mi);


            Color color = Color.FromRgb(239, 239, 239);

            List<Move> moveList = new List<Move>();
            GameManager.MoveHistory.GetMovesDone(moveList);
            AddMoveList(moveList, color, ref firstMove, ref moveIndex);
            
            int sel = uxGameList.Items.Count - 1;           

            moveList.Clear();
            GameManager.MoveHistory.GetMovesToDo(moveList);
            AddMoveList(moveList, color, ref firstMove, ref moveIndex, true);
            moveList.Clear();

            CommitMove();

            if (uxGameList.Items.Count > 0 && sel < 0)
                sel = 0;

            if (sel >= 0)
            {
                uxGameList.ScrollIntoView(uxGameList.Items[sel]);
           } 
        }

        protected void AddMoveList(List<Move> moveList, Color color, ref bool firstMove, ref int moveIndex, bool currentMove = false)
        {
            foreach (Move move in moveList)
            {
                string sMoveText = GameManager.MoveToString(move, uxNumberNotation.IsChecked.Value);
                AddMove(sMoveText, move, color, ref firstMove, ref moveIndex, currentMove);
                currentMove = false;

                firstMove = !firstMove;
            }
        }

        protected void AddMove(string moveText, Move move, Color color, ref bool firstMove, ref int moveIndex, bool currentMove = false)
        {

            if (_boardItem == null)
            {
                _boardItem = new MoveItem();
                _boardItem.Index = moveIndex.ToString();
                _boardItem.WhiteMoveColor = new SolidColorBrush(color);
                _boardItem.BlackMoveColor = new SolidColorBrush(color);
                _boardItem.CurrentMoveWhite = false;
                _boardItem.CurrentMoveBlack = false;
            }

            if (firstMove == true)
            {
                _boardItem.WhiteMove = moveText;
                _boardItem.WhiteMoveObject = move;
                _boardItem.WhiteMoveColor = new SolidColorBrush(color);
                if (currentMove == true)
                    _boardItem.CurrentMoveWhite = true;

            }
            else
            {
                _boardItem.BlackMove = moveText;
                _boardItem.BlackMoveObject = move;
                _boardItem.BlackMoveColor = new SolidColorBrush(color);
                if (currentMove == true)
                    _boardItem.CurrentMoveBlack = true;
            }


            if (firstMove == false)
            {
                CommitMove();
                moveIndex++;
            }
        }

        protected void CommitMove()
        {
            if (_boardItem != null)
            {
                int rowIdx = uxGameList.Items.Add(_boardItem);
                _boardItem = null;                   
            }
        }

        void uxNumberNotation_Click(object sender, RoutedEventArgs e)
        {
            RefreshGameList();

            NotationChangedArgs args = new NotationChangedArgs();
            args.NumberNotationOn = uxNumberNotation.IsChecked.Value;
            if (NotationChangedEvent != null)
            {
                NotationChangedEvent(this, args);
            }
        }

        private static string GetMoveStrength(string sKey)
        {
            const string keyValue = "Value";
            return LanguageContext.Instance.Dictionary.Translate<string>(sKey, keyValue);

        }

        protected class MoveItem 
        {
            public string Index
            { get; set; }

            public string WhiteMove
            { get; set; }

            public string BlackMove
            { get; set; }

            public Brush WhiteMoveColor
            { get; set; }

            public Brush BlackMoveColor
            { get; set; }

            public Move WhiteMoveObject
            { get; set; }

            public Move BlackMoveObject
            { get; set; }

            public bool CurrentMoveWhite
            { get; set; }

            public bool CurrentMoveBlack
            { get; set; }

        }

        protected class StrengthMenuItem
        {
            public string TextKey
            { get; set; }

            public string DisplayText
            { get; set; }

            public string MoveStrength
            { get; set; }
        }

        #endregion

    }
}
